﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Comissoes.Security;
using Comissoes.Utilities;

namespace Comissoes.Models
{
    public class NotasFiscaisModel
    {
        xcontEntities db = new xcontEntities();
        public NOTAS_FISCAIS nf { get; set; }
        public List<String> erros { get; private set; }

        /// <summary>
        /// Confirma se a nota fiscal possui erros de validação
        /// </summary>
        /// <returns></returns>
        public Boolean SemErros()
        {
            return !this.erros.Any();
        }
        
        /// <summary>
        /// Adiciona o exception a lista de erros
        /// </summary>
        /// <param name="ex">Exception</param>
        private void AddException(Exception ex)
        {
            this.erros.Add(ex.Message);
            if (ex.InnerException != null)
            {
                erros.Add(ex.InnerException.Message);
            }
        }

        #region DropDowns

        public SelectList COD_CDPG { get; private set; }
        public SelectList COD_LISTA { get; private set; }
        public SelectList ID_CID { get; private set; }
        public SelectList ID_NCM { get; private set; }
        public SelectList ID_NTOP { get; private set; }
        public SelectList ID_NTOP_ITVD { get; private set; }
        public SelectList ID_NTOP_TRAN { get; private set; }
        public SelectList ID_UF { get; private set; }
        public SelectList ID_VEIC { get; private set; }

        public SelectList FINALIDADE_NF { get; private set; }
        public SelectList MODFRETE_NF { get; private set; }
        public SelectList AMBIENTE_NF { get; private set; }
        public SelectList TIPODANFE_NF { get; private set; }
        public SelectList TIPOEMISSAO_NF { get; private set; }
        public SelectList TIPOOP_NF { get; private set; }

        public SelectList CSOSN_ITVD { get; private set; }
        public SelectList SICMS_ITVD { get; private set; }
        public SelectList SIPI_ITVD { get; private set; }
        public SelectList INDTOT_ITVD { get; private set; }
        public SelectList MICMS_ITVD { get; private set; }
        public SelectList MICMSST_ITVD { get; private set; }
        public SelectList MOTDESICMS_ITVD { get; private set; }
        public SelectList OICMS_ITVD { get; private set; }
        public SelectList SPISCOFINS_ITVD { get; private set; }
        public SelectList SISSQN_ITVD { get; private set; }
        public SelectList TIPOCALCULO_ITVD { get; private set; }
        public SelectList TIPOESPECIFICO_ITVD { get; private set; }

        public SelectList CONDICAO_VEIC { get; private set; }
        public SelectList CORDENATRAN_VEIC { get; private set; }
        public SelectList ESPECIE_VEIC { get; private set; }
        public SelectList ORIGEM_VEIC { get; private set; }
        public SelectList RESTRICAO_VEIC { get; private set; }
        public SelectList TIPOCOMB_VEIC { get; private set; }
        public SelectList TIPO_VEIC { get; private set; }
        public SelectList TIPOOP_VEIC { get; private set; }
        public SelectList VIN_VEIC { get; private set; }

        public SelectList TIPO_ARMA { get; private set; }

        #endregion

        public NotasFiscaisModel()
        {
            this.nf = new NOTAS_FISCAIS
            {
                MODELO_NF = 55,
                VERSAOXML_NF = "2.0",
                VERSAOMR_NF = System.Configuration.ConfigurationManager.AppSettings["AppTitle"],
                VENDAS = new VENDAS()
            };

            this.erros = new List<string>();
            this.CreateSelectList();
        }

        public NotasFiscaisModel(Int32? ID_NF)
        {
            try
            {
                if (ID_NF.HasValue && ID_NF != 0)
                {
                    this.nf = db.NOTAS_FISCAIS.FirstOrDefault(t => t.ID_NF == ID_NF);

                    this.nf.VENDASReference.Load();
                    this.nf.VENDAS.CLIENTESReference.Load();
                    this.nf.VENDAS.CLIENTES.PESSOASReference.Load();

                    this.nf.VENDAS.CLIENTESReference.Load();
                    this.nf.VENDAS.CLIENTES.PESSOASReference.Load();

                    this.nf.VENDAS.LOJASReference.Load();
                    this.nf.VENDAS.LOJAS.PESSOASReference.Load();
                    this.nf.VENDAS.LOJAS.REGIMES_TRIBUTARIOSReference.Load();

                    this.nf.VENDAS.TRANSPORTADORESReference.Load();
                    if (this.nf.VENDAS.TRANSPORTADORES != null)
                    {
                        this.nf.VENDAS.TRANSPORTADORES.PESSOASReference.Load();
                    }

                    this.nf.VENDAS.CONDICOES_PAGAMENTOReference.Load();

                    this.nf.VENDAS.ENDERECO_LOJAReference.Load();
                    this.nf.VENDAS.ENDERECO_CLIENTEReference.Load();
                    this.nf.VENDAS.ENDERECO_TRANSPORTADORReference.Load();
                    this.nf.VENDAS.ENDERECO_RETIRADAReference.Load();
                    this.nf.VENDAS.ENDERECO_ENTREGAReference.Load();

                    nf.CIDADESReference.Load();
                }
                else
                {
                    this.nf = new NOTAS_FISCAIS
                    {
                        MODELO_NF = 55,
                        VERSAOXML_NF = "2.0",
                        VERSAOMR_NF = System.Configuration.ConfigurationManager.AppSettings["AppTitle"],
                        VENDAS = new VENDAS()
                    };
                }

                this.erros = new List<string>();
                this.CreateSelectList();
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Gerar número e série da nota fiscal
        /// </summary>
        /// <param name="COD_LOJA"></param>
        public Object GerarNumeroSerieNF(Int32 COD_LOJA)
        {
            try
            {
                LOJAS loja = db.LOJAS.Include("REGIMES_TRIBUTARIOS").FirstOrDefault(t => t.COD_LOJA == COD_LOJA);

                if (this.nf.ID_NF == 0)
                {
                    String numero = "1";
                    Int32 serie = 1;

                    if (db.NOTAS_FISCAIS.Any(t => t.VENDAS.LOJAS.COD_LOJA == COD_LOJA))
                    {
                        NOTAS_FISCAIS n = db.NOTAS_FISCAIS.Where(t => t.VENDAS.LOJAS.COD_LOJA == COD_LOJA).OrderByDescending(t => t.ID_NF).First();

                        if (n.NUMERO_NF == "999999999")
                        {
                            serie = (Int32)n.SERIE_NF++;
                        }
                        else
                        {
                            numero = (Int64.Parse(n.NUMERO_NF) + 1).ToString();
                            serie = (Int32)n.SERIE_NF;
                        }
                    }

                    this.nf.NUMERO_NF = numero.PadLeft(9, '0');
                    this.nf.SERIE_NF = serie;
                }

                return new
                {
                    NUMERO_NF = this.nf.NUMERO_NF,
                    SERIE_NF = this.nf.SERIE_NF,
                    ID_RGTR = loja.REGIMES_TRIBUTARIOS.ID_RGTR
                };
            }
            catch (Exception ex)
            {
                this.AddException(ex);
                return null;
            }
        }

        /// <summary>
        /// Valida os dados informados para salvar a nota fiscal
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public void Validate(FormCollection form)
        {
            if (String.IsNullOrEmpty(form["EMISSAO_NF"])) this.erros.Add("É necessário informar a data de emissão da nota.");
            if (String.IsNullOrEmpty(form["MODELO_NF"])) this.erros.Add("É necessário informar o modelo do documento fiscal.");
            if (String.IsNullOrEmpty(form["SERIE_NF"])) this.erros.Add("É necessário informar a série do documento fiscal.");
            if (String.IsNullOrEmpty(form["NUMERO_NF"])) this.erros.Add("É necessário informar o número do documento fiscal.");
            if (String.IsNullOrEmpty(form["TIPOEMISSAO_NF"])) this.erros.Add("É necessário informar a forma de emissão do documento fiscal.");
            if (String.IsNullOrEmpty(form["ID_NTOP_NF"])) this.erros.Add("É necessário informar a natureza de operação do documento fiscal.");
            if (String.IsNullOrEmpty(form["COD_LOJA"])) this.erros.Add("É necessário informar a loja.");
            if (String.IsNullOrEmpty(form["COD_CLI"])) this.erros.Add("É necessário informar o cliente.");
            if (String.IsNullOrEmpty(form["COD_CDPG"])) this.erros.Add("É necessário informar a condição de pagamento.");
            if (String.IsNullOrEmpty(form["ENPS_LOJA"])) this.erros.Add("É necessário informar o endereço da loja.");
            if (String.IsNullOrEmpty(form["ENPS_CLI"])) this.erros.Add("É necessário informar o endereço do cliente.");
            if (!String.IsNullOrEmpty(form["COD_TRAN"]) && String.IsNullOrEmpty(form["ENPS_TRAN"])) this.erros.Add("É necessário informar o endereço do transportador.");
        }

        /// <summary>
        /// Atualiza os dados da nota fiscal
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public void Update(FormCollection form)
        {
            try
            {
                Int32? COD_CDPG = Convertions.Inteiro(form["COD_CDPG"]);
                Int32? ID_NTOP = Convertions.Inteiro(form["ID_NTOP_NF"]);
                Int32? COD_LOJA = Convertions.Inteiro(form["COD_LOJA"]);
                Int32? COD_CLI = Convertions.Inteiro(form["COD_CLI"]);
                Int32? COD_TRAN = Convertions.Inteiro(form["COD_TRAN"]);
                Int32? ENPS_LOJA = Convertions.Inteiro(form["ENPS_LOJA"]);
                Int32? ENPS_CLI = Convertions.Inteiro(form["ENPS_CLI"]);
                Int32? ENPS_TRAN = Convertions.Inteiro(form["ENPS_TRAN"]);
                Int32? ENPS_ENTR = Convertions.Inteiro(form["ENPS_ENTR"]);
                Int32? ENPS_RET = Convertions.Inteiro(form["ENPS_RET"]);

                ENDERECOS_PESSOA endereco = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_LOJA);
                endereco.ENDERECOSReference.Load();
                endereco.ENDERECOS.BAIRROSReference.Load();
                endereco.ENDERECOS.BAIRROS.CIDADESReference.Load();

                this.nf.FINALIDADE_NF = Convertions.Inteiro(form["FINALIDADE_NF"]);
                this.nf.VENDAS.CONDICOES_PAGAMENTO = db.CONDICOES_PAGAMENTO.FirstOrDefault(t => t.COD_CDPG == COD_CDPG);
                this.nf.AMBIENTE_NF = Convertions.Inteiro(form["AMBIENTE_NF"]);
                this.nf.TIPODANFE_NF = Convertions.Inteiro(form["TIPODANFE_NF"]);
                this.nf.TIPOOP_NF = form["TIPOOP_NF"];
                this.nf.NUMERO_NF = form["NUMERO_NF"];
                this.nf.CIDADES = endereco.ENDERECOS.BAIRROS.CIDADES;
                this.nf.MODELO_NF = Convertions.Inteiro(form["MODELO_NF"]);
                this.nf.SERIE_NF = Convertions.Inteiro(form["SERIE_NF"]);
                this.nf.TIPOEMISSAO_NF = form["TIPOEMISSAO_NF"];
                this.nf.EMISSAO_NF = Convertions.Data(form["EMISSAO_NF"]);
                this.nf.SAIENT_NF = Convertions.Data(form["SAIENT_NF"]);

                this.nf.VENDAS.NATUREZAS_OPERACAO = db.NATUREZAS_OPERACAO.FirstOrDefault(t => t.ID_NTOP == ID_NTOP);
                this.nf.VENDAS.LOJAS = db.LOJAS.FirstOrDefault(t => t.COD_LOJA == COD_LOJA);
                this.nf.VENDAS.CLIENTES = db.CLIENTES.FirstOrDefault(t => t.COD_CLI == COD_CLI);
                this.nf.VENDAS.TRANSPORTADORES = db.TRANSPORTADORES.FirstOrDefault(t => t.COD_TRAN == COD_TRAN);
                this.nf.VENDAS.ENDERECO_LOJA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_LOJA);
                this.nf.VENDAS.ENDERECO_CLIENTE = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_CLI);
                this.nf.VENDAS.ENDERECO_TRANSPORTADOR = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_TRAN);
                this.nf.VENDAS.ENDERECO_RETIRADA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_RET);
                this.nf.VENDAS.ENDERECO_ENTREGA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_ENTR);

                this.GerarChave(COD_LOJA);
                this.SaveChanges();

                if (this.SemErros())
                {
                    UpdateVenda(form);

                    this.SituacaoNF("A");
                }
            }
            catch (Exception ex)
            {
                this.AddException(ex);
            }
        }

        /// <summary>
        /// Atualizar dados da venda
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        private VENDAS UpdateVenda(FormCollection form)
        {
            try
            {
                VENDAS venda;

                if (db.PEDIDOS_VENDA.Any(t => t.NOTAS_FISCAIS.ID_NF == this.nf.ID_NF))
                {
                    this.nf.VENDAS = db.PEDIDOS_VENDA.FirstOrDefault(t => t.NOTAS_FISCAIS.ID_NF == this.nf.ID_NF).VENDAS;

                    this.SaveChanges();

                    return this.nf.VENDAS;
                }

                else if (this.nf.VENDAS == null)
                {
                    venda = new VENDAS();
                    db.AddToVENDAS(venda);
                    venda.OPERADORES = db.OPERADORES.FirstOrDefault(t => t.ID_OPER == Access.User.ID_OPER);

                    this.nf.VENDAS = venda;
                }
                else
                {
                    venda = this.nf.VENDAS;
                }

                Int32? ID_NTOP = Convertions.Inteiro(form["ID_NTOP_NF"]);
                Int32? COD_CDPG = Convertions.Inteiro(form["COD_CDPG"]);
                Int32? COD_LOJA = Convertions.Inteiro(form["COD_LOJA"]);
                Int32? COD_CLI = Convertions.Inteiro(form["COD_CLI"]);
                Int32? COD_TRAN = Convertions.Inteiro(form["COD_CLI"]);
                Int32? COD_VEND = Convertions.Inteiro(form["COD_VEND"]);
                Int32? ENPS_RET = Convertions.Inteiro(form["ENPS_RET"]);
                Int32? ENPS_ENTR = Convertions.Inteiro(form["COD_VEND"]);

                venda.DATA_VDA = Convertions.Data(form["DATA_VDA"]);
                venda.VENDEDORES = db.VENDEDORES.FirstOrDefault(t => t.COD_VEND == COD_VEND);
                venda.CLIENTES = db.CLIENTES.FirstOrDefault(t => t.COD_CLI == COD_CLI);
                venda.TRANSPORTADORES = db.TRANSPORTADORES.FirstOrDefault(t => t.COD_TRAN == COD_TRAN);
                venda.ENDERECO_RETIRADA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_RET);
                venda.ENDERECO_ENTREGA = db.ENDERECOS_PESSOA.FirstOrDefault(t => t.ID_ENPS == ENPS_ENTR);
                venda.LOJAS = db.LOJAS.FirstOrDefault(t => t.COD_LOJA == COD_LOJA);
                venda.NATUREZAS_OPERACAO = db.NATUREZAS_OPERACAO.FirstOrDefault(t => t.ID_NTOP == ID_NTOP);
                venda.MODFRETE_VDA = form["MODFRETE_VDA"];

                SaveChanges();

                UpdateTotalVenda(form);

                return venda;
            }
            catch (Exception ex)
            {
                AddException(ex);
                return null;
            }
        }

        /// <summary>
        /// Atualizar totais da venda
        /// </summary>
        /// <param name="form"></param>
        private void UpdateTotalVenda(FormCollection form)
        {
            try
            {
                if (this.nf.VENDAS != null && db.ITENS_VENDA.Any(t => t.VENDAS.ID_VDA == this.nf.VENDAS.ID_VDA))
                {
                    IQueryable<ITENS_VENDA> itens = db.ITENS_VENDA.Where(t => t.VENDAS.ID_VDA == this.nf.VENDAS.ID_VDA);

                    VENDAS venda = db.VENDAS.FirstOrDefault(t => t.ID_VDA == this.nf.VENDAS.ID_VDA);

                    venda.ACRESCIMO_VDA = Convertions.Decimal(form["ACRESCIMO_VDA"]);
                    venda.SERVICO_VDA = Convertions.Decimal(form["SERVICO_VDA"]);
                    venda.TXENTR_VDA = Convertions.Decimal(form["TXENTR_VDA"]);

                    venda.BICMS_VDA = itens.Sum(t => t.QTDE_ITVD * t.PRODUTOS_LISTA.PRECO_PDLS) ?? 0;
                    venda.BICMSST_VDA = itens.Sum(t => (t.QTDE_ITVD * t.PRODUTOS_LISTA.PRECO_PDLS)) ?? 0;
                    venda.BISSQN_VDA = itens.Sum(t => (t.PRODUTOS_LISTA.ISSQN_PDLS ?? 0) * (t.QTDE_ITVD * t.PRODUTOS_LISTA.PRECO_PDLS)) ?? 0;
                    venda.COFINS_VDA = itens.Sum(t => t.COFINS_ITVD) ?? 0;
                    venda.DESCONTO_VDA = itens.Sum(t => t.DESCONTO_ITVD) ?? 0;
                    venda.ICMS_VDA = itens.Sum(t => t.ICMS_ITVD) ?? 0;
                    venda.II_VDA = itens.Sum(t => t.II_ITVD) ?? 0;
                    venda.IPI_VDA = itens.Sum(t => t.IPI_ITVD) ?? 0;
                    venda.ISSQN_VDA = itens.Sum(t => t.ISSQN_ITVD) ?? 0;
                    venda.PIS_VDA = itens.Sum(t => t.PIS_ITVD) ?? 0;
                    venda.SEGURO_VDA = itens.Sum(t => t.SEGURO_ITVD) ?? 0;

                    venda.VLRMERC_VDA = itens.Sum(t => t.QTDE_ITVD * t.PRODUTOS_LISTA.PRECO_PDLS);
                    venda.VLRTOT_VDA = venda.VLRTOT_VDA +
                                        venda.ICMS_VDA +
                                        venda.ICMSST_VDA +
                                        venda.II_VDA +
                                        venda.IPI_VDA +
                                        venda.ISSQN_VDA +
                                        venda.PIS_VDA +
                                        venda.SEGURO_VDA -
                                        venda.DESCONTO_VDA;
                }
            }
            catch (Exception ex)
            {
                AddException(ex);
            }
        }

        /// <summary>
        /// validar os dados do produto informado
        /// </summary>
        /// <returns></returns>
        private void ValidateItenVenda(FormCollection form)
        {
            List<String> erros = new List<string>();

            switch (form["SICMS_ITVD"])
            {
                case "00":
                    if (String.IsNullOrEmpty(form["MICMS_ITVD"])) this.erros.Add("É necessário informar a modalidade de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["BICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["PICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de icms.");
                    if (String.IsNullOrEmpty(form["ICMS_ITVD"])) this.erros.Add("É necessário informar o valor do icms.");
                    break;
                case "10":
                    if (String.IsNullOrEmpty(form["MICMS_ITVD"])) this.erros.Add("É necessário informar a modalidade de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["BICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["PICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de icms.");
                    if (String.IsNullOrEmpty(form["ICMS_ITVD"])) this.erros.Add("É necessário informar o valor do icms.");
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o total de icmsst.");
                    break;
                case "|10":
                case "|90":
                    if (String.IsNullOrEmpty(form["MICMS_ITVD"])) this.erros.Add("É necessário informar a modalidade de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["BICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["PICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de icms.");
                    if (String.IsNullOrEmpty(form["ICMS_ITVD"])) this.erros.Add("É necessário informar o valor do icms.");
                    if (String.IsNullOrEmpty(form["OPICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms na operação própria.");
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o valor do icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ID_UF_ITVD"])) this.erros.Add("É necessário informar o uf devido na operação de icmsst.");
                    break;
                case "20":
                case "51":
                    if (String.IsNullOrEmpty(form["MICMS_ITVD"])) this.erros.Add("É necessário informar a modalidade de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["RICMS_ITVD"])) this.erros.Add("É necessário informar o percentual de redução da base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["BICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["PICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de icms.");
                    if (String.IsNullOrEmpty(form["ICMS_ITVD"])) this.erros.Add("É necessário informar o valor do icms.");
                    break;
                case "30":
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o valor do icmsst.");
                    break;
                case "|41":
                    if (String.IsNullOrEmpty(form["BICMSST_UF_REM_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst retido na uf remetente.");
                    if (String.IsNullOrEmpty(form["ICMSST_UF_REM_ITVD"])) this.erros.Add("É necessário informar o valor de icmsst retido na uf remetente.");
                    if (String.IsNullOrEmpty(form["BICMSST_UF_DEST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst retido na uf de destino.");
                    if (String.IsNullOrEmpty(form["BICMSST_UF_DEST_ITVD"])) this.erros.Add("É necessário informar o valor de icmsst retido na uf de destino.");
                    break;
                case "60":
                    if (String.IsNullOrEmpty(form["BICMSST_RETIDO_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst retido anteriormente.");
                    if (String.IsNullOrEmpty(form["ICMSST_RETIDO_ITVD"])) this.erros.Add("É necessário informar o valor de icmsst retido anteriormente.");
                    break;
                case "70":
                    if (String.IsNullOrEmpty(form["MICMS_ITVD"])) this.erros.Add("É necessário informar a modalidade de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["RICMS_ITVD"])) this.erros.Add("É necessário informar o percentual de redução da base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["BICMS_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms.");
                    if (String.IsNullOrEmpty(form["PICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de icms.");
                    if (String.IsNullOrEmpty(form["ICMS_ITVD"])) this.erros.Add("É necessário informar o valor do icms.");
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo de icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o valor do icmsst.");
                    break;
            }

            switch (form["CSOSN_ITVD"])
            {
                case "101":
                    if (String.IsNullOrEmpty(form["PCREDICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de cálculo do crédito do icms.");
                    if (String.IsNullOrEmpty(form["CREDITOICMS_ITVD"])) this.erros.Add("É necessário informar o valor de crédito do icms");
                    break;
                case "201":
                    if (String.IsNullOrEmpty(form["PCREDICMS_ITVD"])) this.erros.Add("É necessário informar a alíquota de cálculo do crédito do icms.");
                    if (String.IsNullOrEmpty(form["CREDITOICMS_ITVD"])) this.erros.Add("É necessário informar o valor de crédito do icms");
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o total de icmsst.");
                    break;
                case "202":
                case "203":
                    if (String.IsNullOrEmpty(form["MICMSST_ITVD"])) this.erros.Add("É necessário informar a modalidade de determinação da base de cálculo do icmsst");
                    if (String.IsNullOrEmpty(form["BICMSST_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icmsst.");
                    if (String.IsNullOrEmpty(form["PICMSST_ITVD"])) this.erros.Add("É necessário informar a alíquota de icmsst.");
                    if (String.IsNullOrEmpty(form["ICMSST_ITVD"])) this.erros.Add("É necessário informar o total de icmsst.");
                    break;
                case "500":
                    if (String.IsNullOrEmpty(form["BICMSST_RETIDO_ITVD"])) this.erros.Add("É necessário informar a base de cálculo do icms cobrado anteriormente");
                    if (String.IsNullOrEmpty(form["ICMSST_RETIDO_ITVD"])) this.erros.Add("É necessário informar o valor de icms cobrado anteriormente.");
                    break;
            }
        }

        /// <summary>
        /// Atualizar itens da nota fiscal
        /// </summary>
        /// <param name="form"></param>
        /// <param name="ID_ITVD"></param>
        /// <returns></returns>
        public void UpdateItenVenda(FormCollection form)
        {
            ValidateItenVenda(form);

            if (this.SemErros())
            {
                try
                {

                    Int32? ID_ITVD = Convertions.Inteiro(form["ID_ITVD"]),
                           COD_PROD = Convertions.Inteiro(form["COD_PROD"]);

                    ITENS_VENDA iten;
                    Int32? COD_LISTA = Convertions.Inteiro(form["COD_LISTA"]);
                    PRODUTOS_LISTA produto = db.PRODUTOS_LISTA.FirstOrDefault(t => t.PRODUTOS.COD_PROD == COD_PROD && t.LISTAS.COD_LISTA == COD_LISTA);

                    if (ID_ITVD.HasValue)
                    {
                        iten = db.ITENS_VENDA.FirstOrDefault(t => t.ID_ITVD == ID_ITVD);
                    }
                    else
                    {
                        if (db.PEDIDOS_VENDA.Any(t => t.NOTAS_FISCAIS.ID_NF == this.nf.ID_NF))
                        {
                            PEDIDOS_VENDA pedido = db.PEDIDOS_VENDA.Include("NOTAS_FISCAIS").FirstOrDefault(t => t.NOTAS_FISCAIS.ID_NF == this.nf.ID_NF);

                            iten = new ITENS_VENDA
                            {
                                ITEM_ITVD = db.ITENS_VENDA.Include("VENDAS").Count(t => t.VENDAS.ID_VDA == pedido.VENDAS.ID_VDA) + 1
                            };
                        }
                        else
                        {
                            iten = new ITENS_VENDA
                            {
                                ITEM_ITVD = db.ITENS_VENDA.Include("VENDAS").Where(t => t.VENDAS.ID_VDA == this.nf.VENDAS.ID_VDA).Count() + 1,
                                VENDAS = this.UpdateVenda(form)
                            };
                        }

                        db.AddToITENS_VENDA(iten);
                    }

                    Int32? COD_VEND = Convertions.Inteiro(form["COD_VEND"]);
                    iten.VENDEDORES = db.VENDEDORES.FirstOrDefault(t => t.COD_VEND == COD_VEND);

                    Int32? ID_NTOP_ITVD = Convertions.Inteiro(form["ID_NTOP_ITVD"]);
                    iten.NATUREZAS_OPERACAO = db.NATUREZAS_OPERACAO.FirstOrDefault(t => t.ID_NTOP == ID_NTOP_ITVD);

                    iten.QTDE_ITVD = Convertions.Decimal(form["QTDE_ITVD"]);
                    iten.QTDEENT_ITVD = Convertions.Decimal(form["QTDEENT_ITVD"]) ?? iten.QTDE_ITVD;
                    iten.DESCONTO_ITVD = Convertions.Decimal(form["DESCONTO_ITVD"]);
                    iten.DESP_ACESSORIA_ITVD = Convertions.Decimal(form["DESP_ACESSORIA_ITVD"]);
                    iten.FRETE_ITVD = Convertions.Decimal(form["FRETE_ITVD"]);
                    iten.INDTOT_ITVD = form["INDTOT_ITVD"].Contains("true") ? 0 : 1;

                    if (!String.IsNullOrEmpty(form["SICMS_ITVD"]) || !String.IsNullOrEmpty(form["CSOSN_ITVD"]))
                    {
                        iten.SICMS_ITVD = form["SICMS_ITVD"] ?? form["CSOSN_ITVD"];

                        iten.OICMS_ITVD = form["OICMS_ITVD"];
                        iten.MICMS_ITVD = form["MICMS_ITVD"];

                        iten.PCREDICMS_ITVD = Convertions.Decimal(form["PCREDICMS_ITVD"]);
                        iten.CREDITOICMS_ITVD = Convertions.Decimal(form["CREDITOICMS_ITVD"]);
                        iten.ICMS_ITVD = Convertions.Decimal(form["ICMS_ITVD"]);
                        iten.MOTDESICMS_ITVD = form["MOTDESICMS_ITVD"];
                        iten.BICMSST_RETIDO_ITVD = Convertions.Decimal(form["BICMSST_RETIDO_ITVD"]);
                        iten.ICMSST_RETIDO_ITVD = Convertions.Decimal(form["ICMSST_RETIDO_ITVD"]);
                        iten.BICMSST_UF_REM_ITVD = Convertions.Decimal(form["BICMSST_UF_REM_ITVD"]);
                        iten.ICMSST_UF_REM_ITVD = Convertions.Decimal(form["ICMSST_UF_REM_ITVD"]);
                        iten.BICMSST_UF_DEST_ITVD = Convertions.Decimal(form["BICMSST_UF_DEST_ITVD"]);
                        iten.ICMSST_UF_DEST_ITVD = Convertions.Decimal(form["ICMSST_UF_DEST_ITVD"]);
                        iten.PCREDICMS_ITVD = Convertions.Decimal(form["PCREDICMS_ITVD"]);
                        iten.CREDITOICMS_ITVD = Convertions.Decimal(form["CREDITOICMS_ITVD"]);

                        iten.MICMS_ITVD = form["MICMS_ITVD"];
                        iten.RICMS_ITVD = Convertions.Decimal(form["RICMS_ITVD"]);
                        iten.BICMS_ITVD = Convertions.Decimal(form["BICMS_ITVD"]);
                        iten.PICMS_ITVD = Convertions.Decimal(form["PICMS_ITVD"]);
                        iten.ICMS_ITVD = Convertions.Decimal(form["ICMS_ITVD"]);
                        iten.OPICMS_ITVD = Convertions.Decimal(form["OPICMS_ITVD"]);

                        iten.MICMSST_ITVD = form["MICMSST_ITVD"];
                        iten.RICMSST_ITVD = Convertions.Decimal(form["RICMSST_ITVD"]);
                        iten.MVAICMSST_ITVD = Convertions.Decimal(form["MVAICMSST_ITVD"]);
                        iten.BICMSST_ITVD = Convertions.Decimal(form["BICMSST_ITVD"]);
                        iten.PICMSST_ITVD = Convertions.Decimal(form["PICMSST_ITVD"]);
                        iten.ICMSST_ITVD = Convertions.Decimal(form["ICMSST_ITVD"]);

                        Int32? ID_UF = Convertions.Inteiro(form["ICMSST_ID_UF_ITVD"]);

                        iten.UFS = db.UFS.FirstOrDefault(t => t.ID_UF == ID_UF);
                    }

                    if (!String.IsNullOrEmpty(form["SCOFINS_ITVD"]))
                    {
                        iten.COFINS_ITVD = Convertions.Decimal(form["COFINS_ITVD"]);
                        iten.BCOFINS_ITVD = Convertions.Decimal(form["BCOFINS_ITVD"]);
                        iten.PCOFINS_ITVD = Convertions.Decimal(form["PCOFINS_ITVD"]);
                        iten.QCOFINS_ITVD = Convertions.Decimal(form["QCOFINS_ITVD"]);
                        iten.SCOFINS_ITVD = form["SCOFINS_ITVD"];
                        iten.TCOFINS_ITVD = form["TCOFINS_ITVD"];
                        iten.VCOFINS_ITVD = Convertions.Decimal(form["VCOFINS_ITVD"]);
                    }

                    if (!String.IsNullOrEmpty(form["SPIS_ITVD"]))
                    {
                        iten.PIS_ITVD = Convertions.Decimal(form["PIS_ITVD"]);
                        iten.BPIS_ITVD = Convertions.Decimal(form["BPIS_ITVD"]);
                        iten.PPIS_ITVD = Convertions.Decimal(form["PPIS_ITVD"]);
                        iten.QPIS_ITVD = Convertions.Decimal(form["QPIS_ITVD"]);
                        iten.SPIS_ITVD = form["SPIS_ITVD"];
                        iten.TPIS_ITVD = form["TPIS_ITVD"];
                        iten.VPIS_ITVD = Convertions.Decimal(form["VPIS_ITVD"]);
                    }

                    if (!String.IsNullOrEmpty(form["SIPI_ITVD"]))
                    {
                        iten.IPI_ITVD = Convertions.Decimal(form["IPI_ITVD"]);
                        iten.BIPI_ITVD = Convertions.Decimal(form["BIPI_ITVD"]);
                        iten.PIPI_ITVD = Convertions.Decimal(form["PIPI_ITVD"]);
                        iten.QIPI_ITVD = Convertions.Decimal(form["QIPI_ITVD"]);
                        iten.QSELOIPI_ITVD = Convertions.Inteiro(form["QSELOIPI_ITVD"]);
                        iten.SELOIPI_ITVD = form["SELOIPI_ITVD"];
                        iten.SIPI_ITVD = form["SIPI_ITVD"];
                        iten.TIPI_ITVD = form["TIPI_ITVD"];
                        iten.VIPI_ITVD = Convertions.Decimal(form["VIPI_ITVD"]);
                    }

                    if (!String.IsNullOrEmpty(form["ISSQN_ITVD"]))
                    {
                        Int32? ID_CID = Convertions.Inteiro(form["ID_CID_ISSQN_ITVD"]);

                        iten.CIDADES = db.CIDADES.FirstOrDefault(t => t.ID_CID == ID_CID);
                        iten.ISSQN_ITVD = Convertions.Decimal(form["ISSQN_ITVD"]);
                        iten.BISSQN_ITVD = Convertions.Decimal(form["BISSQN_ITVD"]);
                        iten.PISSQN_ITVD = Convertions.Decimal(form["PISSQN_ITVD"]);
                        iten.SEGURO_ITVD = Convertions.Decimal(form["SEGURO_ITVD"]);
                        iten.TISSQN_ITVD = form["TISSQN_ITVD"];
                    }

                    if (!String.IsNullOrEmpty(form["IOFII_ITVD"]))
                    {
                        iten.II_ITVD = Convertions.Decimal(form["II_ITVD"]);
                        iten.BII_ITVD = Convertions.Decimal(form["BII_ITVD"]);
                        iten.DESPADUII_ITVD = Convertions.Decimal(form["DESPADUII_ITVD"]);
                        iten.IOFII_ITVD = Convertions.Decimal(form["IOFII_ITVD"]);
                    }

                    SaveChanges();
                }
                catch (Exception ex)
                {
                    this.AddException(ex);
                }
            }
        }

        /// <summary>
        /// Excluir um item da nota fiscal
        /// </summary>
        /// <param name="ID_ITVD"></param>
        /// <param name="ID_VDA"></param>
        /// <returns></returns>
        public void DeleteItenVenda(Int32? ID_ITVD, Int32? ID_VDA)
        {
            List<String> erros = new List<string>();

            try
            {
                ITENS_VENDA item = db.ITENS_VENDA.FirstOrDefault(t => t.ID_ITVD == ID_ITVD);
                db.DeleteObject(item);

                foreach (ITENS_VENDA i in db.ITENS_VENDA.Where(t => t.VENDAS.ID_VDA == ID_VDA && t.ITEM_ITVD > item.ITEM_ITVD))
                {
                    i.ITEM_ITVD--;
                }

                db.SaveChanges();
            }
            catch (Exception ex)
            {
                this.erros.Add(ex.Message);
            }
        }

        /// <summary>
        /// Gera a chave da NF-e
        /// </summary>
        /// <returns></returns>
        private void GerarChave(Int32? COD_LOJA)
        {
            try
            {

                List<Int32> mm = new List<Int32>();
                String chave, digito;

                if (string.IsNullOrEmpty(this.nf.CHAVE_NF))
                {
                    this.nf.CHAVE_NF = string.Format("{0:yyMMddss}", DateTime.Now);
                }

                LOJAS loja = db.LOJAS.Include("PESSOAS").Include("PESSOAS.DOCUMENTOS_PESSOA").Include("PESSOAS.DOCUMENTOS_PESSOA.DOCUMENTOS").FirstOrDefault(t => t.COD_LOJA == COD_LOJA);
                this.nf.CIDADESReference.Load();
                this.nf.CIDADES.UFSReference.Load();

                chave = String.Format("{0}{1:MMyy}{2}{3}{4}{5}{6}{7}",
                    this.nf.CIDADES.UFS.CODIBGE_UF,
                    this.nf.EMISSAO_NF,
                    loja.PESSOAS.DOCUMENTOS_PESSOA.FirstOrDefault(t => t.DOCUMENTOS.COD_DOC == 2).VALOR_PSDC,
                    this.nf.MODELO_NF,
                    this.nf.SERIE_NF.ToString().PadLeft(3, '0'),
                    this.nf.NUMERO_NF.PadLeft(9, '0'),
                    this.nf.TIPOEMISSAO_NF,
                    this.nf.CHAVE_NF);

                if (chave.Length != 43)
                {
                    this.erros.Add("Tamanho da chave inválido.");
                }

                if (!erros.Any())
                {
                    Char[] v = chave.ToCharArray(),
                           m = "4329876543298765432987654329876543298765432".ToCharArray();

                    for (Int32 i = 0; i < m.Length; i++)
                        mm.Add(Int32.Parse(m[i].ToString()) * Int32.Parse(v[i].ToString()));

                    Int32 ponderacao = mm.Sum() % 11;

                    if (ponderacao == 0 || ponderacao == 1)
                        digito = "0";

                    else
                        digito = (11 - ponderacao).ToString();

                    this.nf.CHAVENFE_NF = chave + digito;
                    this.nf.DV_NF = digito;
                }
            }
            catch (Exception ex)
            {
                this.erros.Add(ex.Message);
            }
        }

        /// <summary>
        /// Salva a informação atual no banco de dados
        /// </summary>
        /// <returns></returns>
        private void SaveChanges()
        {
            if (SemErros())
            {
                try
                {
                    db.SaveChanges();
                }
                catch (Exception ex)
                {
                    this.erros.Add(ex.Message);
                }
            }
        }

        /// <summary>
        /// Retorna um objeto com os detalhes do item informado
        /// </summary>
        /// <param name="form"></param>
        /// <returns></returns>
        public Object ItenDetails(Int32 ID_ITVD)
        {
            try
            {
                Object icms = new { empty = true };
                Object ipi = new { empty = true };
                Object pis = new { empty = true };
                Object cofins = new { empty = true };
                Object ii = new { empty = true };
                Object issqn = new { empty = true };

                ITENS_VENDA iten = db.ITENS_VENDA.Include("PRODUTOS_LISTA")
                                                 .Include("PRODUTOS_LISTA.LISTAS")
                                                 .Include("PRODUTOS_LISTA.PRODUTOS")
                                                 .Include("PRODUTOS_LISTA.PRODUTOS.UNIDADES")
                                                 .Include("PRODUTOS_LISTA.PRODUTOS.NCM").First(t => t.ID_ITVD == ID_ITVD);

                if (iten.ICMS_ITVD.HasValue)
                {
                    icms = new
                    {
                        empty = false,
                        SICMS_ITVD = iten.SICMS_ITVD,
                        OICMS_ITVD = iten.OICMS_ITVD,
                        MICMS_ITVD = iten.MICMS_ITVD,
                        BICMS_ITVD = iten.BICMS_ITVD,
                        MVAICMSST_ITVD = iten.MVAICMSST_ITVD,
                        PICMS_ITVD = iten.PICMS_ITVD,
                        RICMS_ITVD = iten.RICMS_ITVD,
                        ICMS_ITVD = iten.ICMS_ITVD
                    };
                }

                if (iten.IPI_ITVD.HasValue)
                {
                    ipi = new
                    {
                        empty = false,
                        SIPI_ITVD = iten.SIPI_ITVD,
                        SELOIPI_ITVD = iten.SELOIPI_ITVD,
                        QSELOIPI_ITVD = iten.QSELOIPI_ITVD,
                        ENQIPI_ITVD = iten.ENQIPI_ITVD,
                        CENQIPI_ITVD = iten.CENQIPI_ITVD,
                        CNPJIPI_ITVD = iten.CNPJIPI_ITVD,
                        TIPI_ITVD = iten.TIPI_ITVD,
                        BIPI_ITVD = iten.BIPI_ITVD,
                        PIPI_ITVD = iten.PIPI_ITVD,
                        QIPI_ITVD = iten.QIPI_ITVD,
                        VIPI_ITVD = iten.VIPI_ITVD,
                        IPI_ITVD = iten.IPI_ITVD
                    };
                }

                if (iten.PIS_ITVD.HasValue)
                {
                    pis = new
                    {
                        empty = false,
                        SPIS_ITVD = iten.SPIS_ITVD,
                        TPIS_ITVD = iten.TPIS_ITVD,
                        BPIS_ITVD = iten.BPIS_ITVD,
                        PPIS_ITVD = iten.PPIS_ITVD,
                        QPIS_ITVD = iten.QPIS_ITVD,
                        VPIS_ITVD = iten.VPIS_ITVD,
                        PIS_ITVD = iten.PIS_ITVD
                    };
                }

                if (iten.COFINS_ITVD.HasValue)
                {
                    cofins = new
                    {
                        empty = false,
                        SCOFINS_ITVD = iten.SCOFINS_ITVD,
                        TCOFINS_ITVD = iten.TCOFINS_ITVD,
                        BCOFINS_ITVD = iten.BCOFINS_ITVD,
                        PCOFINS_ITVD = iten.PCOFINS_ITVD,
                        QCOFINS_ITVD = iten.QCOFINS_ITVD,
                        VCOFINS_ITVD = iten.VCOFINS_ITVD,
                        COFINS_ITVD = iten.COFINS_ITVD
                    };
                }

                if (iten.II_ITVD.HasValue)
                {
                    ii = new
                    {
                        empty = false,
                        BII_ITVD = iten.BII_ITVD,
                        DESPADUII_ITVD = iten.DESPADUII_ITVD,
                        IOFII_ITVD = iten.IOFII_ITVD,
                        II_ITVD = iten.II_ITVD
                    };
                }

                if (iten.ISSQN_ITVD.HasValue)
                {
                    issqn = new
                    {
                        empty = false,
                        TISSQN_ITVD = iten.TISSQN_ITVD,
                        BISSQN_ITVD = iten.BISSQN_ITVD,
                        PISSQN_ITVD = iten.PISSQN_ITVD,
                        ISSQN_ITVD = iten.ISSQN_ITVD,
                        ID_CID_ISSQN = iten.CIDADES.ID_CID,
                        ID_UF_ISSQN = iten.CIDADES.UFS.ID_UF
                    };
                }

                return new
                {
                    DESC_PROD = iten.PRODUTOS_LISTA.PRODUTOS.DESC_PROD,
                    COD_UNID = iten.PRODUTOS_LISTA.PRODUTOS.UNIDADES.COD_UNID,
                    ID_NCM = iten.PRODUTOS_LISTA.PRODUTOS.NCM.ID_NCM,
                    COD_LISTA = iten.PRODUTOS_LISTA.LISTAS.COD_LISTA,
                    tImposto = iten.PRODUTOS_LISTA.PRODUTOS.SERVICOS == null ? "A" : "B",
                    PRECO_PDLS = iten.PRODUTOS_LISTA.PRECO_PDLS,
                    QTDE_ITVD = iten.QTDE_ITVD,
                    FRETE_ITVD = iten.FRETE_ITVD,
                    SEGURO_ITVD = iten.SEGURO_ITVD,
                    DESCONTO_ITVD = iten.DESCONTO_ITVD,
                    TOTAL_ITVD = iten.VLRTOT_ITVD,
                    INFOADI_ITVD = iten.INFOADI_ITVD,
                    icms = icms,
                    ipi = ipi,
                    pis = pis,
                    cofins = cofins,
                    ii = ii,
                    issqn = issqn
                };
            }
            catch (Exception ex)
            {
                this.AddException(ex);
                return null;
            }
        }

        /// <summary>
        /// Cria os dropdowns utilizados na tela de digitação da nota fiscal
        /// </summary>
        private void CreateSelectList()
        {
            List<SelectListItem> FINALIDADE_NF = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "NF-e normal" },
                new SelectListItem { Value = "2", Text = "NF-e complementar" },
                new SelectListItem { Value = "3", Text = "NF-e de ajuste" }
            };

            List<SelectListItem> MODFRETE_NF = new List<SelectListItem> { 
                new SelectListItem { Value = "0", Text = "Emitente" },
                new SelectListItem { Value = "1", Text = "Destinatário/Remetente" },
                new SelectListItem { Value = "2", Text = "Terceiros" },
                new SelectListItem { Value = "9", Text = "Sem Frete" }
            };

            List<SelectListItem> AMBIENTE_NF = new List<SelectListItem> {
                new SelectListItem { Value = "2", Text = "Homologação" },
                new SelectListItem { Value = "1", Text = "Produção" }
            };

            List<SelectListItem> TIPODANFE_NF = new List<SelectListItem> { 
                new SelectListItem { Value = "1", Text = "Retrato" },
                new SelectListItem { Value = "2", Text = "Paisagem" }
            };

            List<SelectListItem> TIPOEMISSAO_NF = new List<SelectListItem> { 
                new SelectListItem { Value = "1", Text = "Normal" },
                new SelectListItem { Value = "2", Text = "Contingência" },                
                new SelectListItem { Value = "3", Text = "Contingência SCAN" },
                new SelectListItem { Value = "4", Text = "Contingência DPEC" },
                new SelectListItem { Value = "5", Text = "Contingência FS-DA" }
            };

            List<SelectListItem> TIPOOP_NF = new List<SelectListItem> { 
                new SelectListItem { Value = "1", Text = "Saída" },
                new SelectListItem { Value = "0", Text = "Entrada" }
            };

            List<SelectListItem> CSOSN_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "101", Text = "101 - Com permissão de crédito" },
                new SelectListItem { Value = "102", Text = "102 - Sem permissão de crédito" },
                new SelectListItem { Value = "103", Text = "103 - Isento" },
                new SelectListItem { Value = "201", Text = "201 - Com permissão de crédito e com cobrança do ICMS por ST" },
                new SelectListItem { Value = "202", Text = "202 - Sem permissão de crédito e com cobrança do ICMS por ST" },
                new SelectListItem { Value = "203", Text = "203 - Isenção od ICMS para faixa de receita bruta e com cobrança do ICMS por ST" },
                new SelectListItem { Value = "300", Text = "300 - Imune" },
                new SelectListItem { Value = "400", Text = "400 - Não tributada pelo simples" },
                new SelectListItem { Value = "500", Text = "500 - Cobrado anterioormente por ST ou antecipação" },
                new SelectListItem { Value = "900", Text = "900 - Outros" }
            };

            List<SelectListItem> SICMS_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "00", Text = "00 - Tributada Integralmente" },
                new SelectListItem { Value = "10", Text = "10 - Tributada e com cobrança do ICMS por ST" },
                new SelectListItem { Value = "|10", Text = "10 - Tributada e com cobrança do ICMS por ST, com partilha entre a UF de origem e UF de destino" },
                new SelectListItem { Value = "20", Text = "20 - Com redução de base de cálculo" },
                new SelectListItem { Value = "30", Text = "30 - Isenta ou não tributada e com cobrança do ICMS por ST" },
                new SelectListItem { Value = "40", Text = "40 - Isenta" },
                new SelectListItem { Value = "41", Text = "41 - Não tributada" },
                new SelectListItem { Value = "|41", Text = "41 - Não tributada (ICMS ST Devida para UF de Destino, produtos com retenção antecipada)" },
                new SelectListItem { Value = "50", Text = "50 - Suspensão" },
                new SelectListItem { Value = "51", Text = "51 - Diferimento" },
                new SelectListItem { Value = "60", Text = "60 - ICMS cobrado anteriormente por ST" },
                new SelectListItem { Value = "70", Text = "70 - Com redução de base de cálculo e cobrança do ICMS por ST" },
                new SelectListItem { Value = "90", Text = "90 - Outros" },
                new SelectListItem { Value = "|90", Text = "90 - Outros, com partilha entre a UF de origem e UF de destino" }
            };

            List<SelectListItem> SIPI_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "00", Text = "00 - Entrada com recuperação de crédito" },
                new SelectListItem { Value = "01", Text = "01 - Entrada tributada com alíquota zero" },
                new SelectListItem { Value = "02", Text = "02 - Entrada isenta" },
                new SelectListItem { Value = "03", Text = "03 - Entrada não-tributada" },
                new SelectListItem { Value = "04", Text = "04 - Entrada imune" },
                new SelectListItem { Value = "05", Text = "05 - Entrada com suspensão" },
                new SelectListItem { Value = "49", Text = "49 - Outras entradas" },
                new SelectListItem { Value = "50", Text = "50 - Saída tributada" },
                new SelectListItem { Value = "51", Text = "51 - Saída tributada com alíquota zero" },
                new SelectListItem { Value = "52", Text = "52 - Saída isenta" },
                new SelectListItem { Value = "53", Text = "53 - Saída não-tributada" },
                new SelectListItem { Value = "54", Text = "54 - Saída imune" },
                new SelectListItem { Value = "55", Text = "55 - Saída com suspensão" },
                new SelectListItem { Value = "99", Text = "99 - Outras Saídas" }
            };

            List<SelectListItem> INDTOT_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "Compõe" },
                new SelectListItem { Value = "0", Text = "Não compõe" }
            };

            List<SelectListItem> MICMS_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "0", Text = "MVA (%)" },
                new SelectListItem { Value = "1", Text = "Pauta" },
                new SelectListItem { Value = "2", Text = "Preço tabelado máximo" },
                new SelectListItem { Value = "3", Text = "Valor da operação" }
            };

            List<SelectListItem> MICMSST_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "0", Text = "Preço tabelado ou máximo" },
                new SelectListItem { Value = "1", Text = "Lista negativa" },
                new SelectListItem { Value = "2", Text = "Lista positiva" },
                new SelectListItem { Value = "3", Text = "Lista neutra" },
                new SelectListItem { Value = "4", Text = "MVA" },
                new SelectListItem { Value = "5", Text = "Pauta" }
            };

            List<SelectListItem> MOTDESICMS_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "Táxi" },
                new SelectListItem { Value = "2", Text = "Deficiente Físico" },
                new SelectListItem { Value = "3", Text = "Produtor Agropecuário" },
                new SelectListItem { Value = "4", Text = "Frotista/Locadora" },
                new SelectListItem { Value = "5", Text = "Diplomático/Consular" },
                new SelectListItem { Value = "6", Text = "Utilitários e Motocicletas da Amazônia Ocidental e Áreas de Livre Comércio" },
                new SelectListItem { Value = "7", Text = "SUFRAMA" },
                new SelectListItem { Value = "9", Text = "Outros" }
            };

            List<SelectListItem> OICMS_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "0", Text = "Nacional" },
                new SelectListItem { Value = "1", Text = "Estrangeira - Importação Direta" },
                new SelectListItem { Value = "2", Text = "Estrangeira - Adquirida no mercado interno" }
            };

            List<SelectListItem> SPISCOFINS_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "01", Text = "01 - A - Cumulativo/Não cumulativo" },
                new SelectListItem { Value = "02", Text = "02 - A - Alíquota diferenciada" },                
                new SelectListItem { Value = "03", Text = "03 - A - Alíquota por unidade de produto" },
                new SelectListItem { Value = "04", Text = "04 - A - Tributação monofásica - alíquota zero" },
                new SelectListItem { Value = "06", Text = "06 - A - Alíquota zero" },
                new SelectListItem { Value = "07", Text = "07 - Isento" },
                new SelectListItem { Value = "08", Text = "08 - Sem incidência" },
                new SelectListItem { Value = "09", Text = "09 - Suspenção" },
                new SelectListItem { Value = "49", Text = "49 - Outras operações de saída" },
                new SelectListItem { Value = "50", Text = "50 - B - Vinculada exclusivamente a receita tributada no mercado interno" },
                new SelectListItem { Value = "51", Text = "51 - B - Vinculada exclusivamente a receita não tributada no mercado interno" },
                new SelectListItem { Value = "52", Text = "52 - B - Vinculada exclusivamente a receita de exportação" },
                new SelectListItem { Value = "53", Text = "53 - B - Vinculada a receitas tributadas e não-tributadas no mercado interno" },
                new SelectListItem { Value = "54", Text = "54 - B - Vinculada a receitas tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "55", Text = "55 - B - Vinculada a receitas não-tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "56", Text = "56 - B - Vinculada a receitas tributadas e não-tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "60", Text = "60 - C - Vinculada exclusivamente a receita tributada no mercado interno" },
                new SelectListItem { Value = "61", Text = "61 - C - Vinculada exclusivamente a receita não tributada no mercado interno" },
                new SelectListItem { Value = "62", Text = "62 - C - Vinculada exclusivamente a receita de exportação" },
                new SelectListItem { Value = "63", Text = "63 - C - Vinculada a receitas tributadas e não-tributadas no mercado interno" },
                new SelectListItem { Value = "64", Text = "64 - C - Vinculada a receitas tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "65", Text = "65 - C - Vinculada a receitas não-tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "66", Text = "66 - C - Vinculada a receitas tributadas e não-tributadas no mercado interno e de exportação" },
                new SelectListItem { Value = "67", Text = "67 - C - Outras operações" },
                new SelectListItem { Value = "70", Text = "70 - D - Sem direito a crédito" },
                new SelectListItem { Value = "71", Text = "71 - D - Com isenção" },
                new SelectListItem { Value = "72", Text = "72 - D - Com suspensão" },
                new SelectListItem { Value = "73", Text = "73 - D - Alíquota zero" },
                new SelectListItem { Value = "74", Text = "74 - D - Sem incidência da contribuição" },
                new SelectListItem { Value = "75", Text = "75 - D - Substituição tributária" },
                new SelectListItem { Value = "98", Text = "98 - Outras operações de entrada" },
                new SelectListItem { Value = "99", Text = "99 - Outras operações" }
            };

            List<SelectListItem> SISSQN_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "N", Text = "Normal" },
                new SelectListItem { Value = "R", Text = "Retida" },
                new SelectListItem { Value = "S", Text = "Substituta" },
                new SelectListItem { Value = "I", Text = "Isenta" }
            };

            List<SelectListItem> TIPOCALCULO_ITVD = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "Percentual" },
                new SelectListItem { Value = "2", Text = "Valor" }
            };

            List<SelectListItem> TIPOESPECIFICO_ITVD = new List<SelectListItem>
            {
                new SelectListItem { Text = "Armamento", Value = "arma" },
                new SelectListItem { Text = "Combustível", Value = "comb" },
                new SelectListItem { Text = "Medicamento", Value = "med" },
                new SelectListItem { Text = "Veículo", Value = "veic" }
            };

            List<SelectListItem> CONDICAO_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "Acabado" },
                new SelectListItem { Value = "2", Text = "Inacabado" },
                new SelectListItem { Value = "3", Text = "Semi-acabado" }
            };

            List<SelectListItem> CORDENATRAN_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "01", Text = "01 - AMARELO" },
                new SelectListItem { Value = "02", Text = "02 - AZUL" },
                new SelectListItem { Value = "03", Text = "03 - BEGE" },
                new SelectListItem { Value = "04", Text = "04 - BRANCA" },
                new SelectListItem { Value = "05", Text = "05 - CINZA" },
                new SelectListItem { Value = "06", Text = "06 - DOURADA" },
                new SelectListItem { Value = "07", Text = "07 - GRENA" },
                new SelectListItem { Value = "08", Text = "08 - LARANJA" },
                new SelectListItem { Value = "09", Text = "09 - MARROM" },
                new SelectListItem { Value = "10", Text = "10 - PRATA" },
                new SelectListItem { Value = "11", Text = "11 - PRETA" },
                new SelectListItem { Value = "12", Text = "12 - ROSA" },
                new SelectListItem { Value = "13", Text = "13 - ROXA" },
                new SelectListItem { Value = "14", Text = "14 - VERDE" },
                new SelectListItem { Value = "15", Text = "15 - VERMELHA" },
                new SelectListItem { Value = "16", Text = "16 - FANTASIA" }
            };

            List<SelectListItem> ESPECIE_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "PASSAGEIRO" },
                new SelectListItem { Value = "2", Text = "CARGA" },
                new SelectListItem { Value = "3", Text = "MISTO" },
                new SelectListItem { Value = "4", Text = "CORRIDA" },
                new SelectListItem { Value = "5", Text = "TRAÇÃO" },
                new SelectListItem { Value = "6", Text = "ESPECIAL" }
            };

            List<SelectListItem> RESTRICAO_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "0", Text = "Não há" },
                new SelectListItem { Value = "1", Text = "Alienação Fiduciária" },
                new SelectListItem { Value = "2", Text = "Arrendamento Mercantil" },
                new SelectListItem { Value = "3", Text = "Reserva de Domínio" },
                new SelectListItem { Value = "4", Text = "Penhor de Veículos" },
                new SelectListItem { Value = "9", Text = "Outras" }
            };

            List<SelectListItem> TIPOCOMB_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "01", Text = "01 - Álcool" },
                new SelectListItem { Value = "02", Text = "02 - Gasolina" },
                new SelectListItem { Value = "03", Text = "03 - Diesel" },
                new SelectListItem { Value = "16", Text = "16 - Álcool/Gasolina" },
                new SelectListItem { Value = "17", Text = "17 - Gasolina/Álcool/GNV" },
                new SelectListItem { Value = "18", Text = "18 - Gasolina/Elétrico" }
            };

            List<SelectListItem> TIPO_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "06", Text = "06 - Automóvel" },
                new SelectListItem { Value = "14", Text = "14 - CAMINHÃO" },
                new SelectListItem { Value = "13", Text = "13 - CAMINHONETA" },
                new SelectListItem { Value = "24", Text = "24 - CARGA / CAM" },
                new SelectListItem { Value = "02", Text = "02 - CICLOMOTO" },
                new SelectListItem { Value = "22", Text = "22 - ESP / ÔNIBUS" },
                new SelectListItem { Value = "07", Text = "07 - MICROÔNIBUS" },
                new SelectListItem { Value = "23", Text = "23 - MISTO / CAM" },
                new SelectListItem { Value = "04", Text = "04 - MOTOCICLO" },
                new SelectListItem { Value = "03", Text = "03 - MOTONETA" },
                new SelectListItem { Value = "08", Text = "08 - ÔNIBUS" },
                new SelectListItem { Value = "10", Text = "10 - REBOQUE" },
                new SelectListItem { Value = "05", Text = "05 - TRICICLO" },
                new SelectListItem { Value = "17", Text = "17 - C. TRATOR" }
            };

            List<SelectListItem> TIPOOP_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "1", Text = "Venda concessionária" },
                new SelectListItem { Value = "2", Text = "Consumidor final" },
                new SelectListItem { Value = "3", Text = "Grandes consumidores (frotista, governo...)"},
                new SelectListItem { Value = "0", Text = "Outros" }
            };

            List<SelectListItem> VIN_VEIC = new List<SelectListItem> {
                new SelectListItem { Value = "N", Text = "Normal" },
                new SelectListItem { Value = "R", Text = "Remarcado" }
            };

            List<SelectListItem> indProc = new List<SelectListItem> {
                new SelectListItem { Value = "0", Text = "SEFAZ" },
                new SelectListItem { Value = "1", Text = "Justiça Federal" },
                new SelectListItem { Value = "2", Text = "Justiça Estadual" },
                new SelectListItem { Value = "3", Text = "Secex/RFB" },
                new SelectListItem { Value = "9", Text = "Outros" }
            };

            List<SelectListItem> TIPO_ARMA = new List<SelectListItem> { 
                new SelectListItem { Value = "0", Text = "Uso Permitido" },
                new SelectListItem { Value = "1", Text = "Uso Restrito" }
            };

            var naturezas = from c in db.NATUREZAS_OPERACAO.ToList()
                            where c.ATIVO_NTOP == "A"
                            && c.CFOP_NTOP % 10 != 0
                            select new
                            {
                                c.ID_NTOP,
                                DESC_NTOP = c.CFOP_NTOP + " - " + c.DESC_NTOP
                            };

            var ncms = from c in db.NCM.ToList()
                       where c.ATIVO_NCM == "A"
                       select new
                       {
                           c.ID_NCM,
                           COD_NCM = c.COD_NCM + " - " + c.DESC_NCM
                       };

            try
            {
                this.COD_CDPG = new SelectList(db.CONDICOES_PAGAMENTO, "COD_CDPG", "DESC_CDPG", this.nf.VENDAS.CONDICOES_PAGAMENTO.COD_CDPG);
            }
            catch
            {
                this.COD_CDPG = new SelectList(db.CONDICOES_PAGAMENTO, "COD_CDPG", "DESC_CDPG");
            }

            this.COD_LISTA = new SelectList(db.LISTAS, "COD_LISTA", "DESC_LISTA");
            this.ID_CID = new SelectList(new Dictionary<string, string>());
            this.ID_NCM = new SelectList(ncms, "ID_NCM", "COD_NCM");

            try
            {
                this.ID_NTOP = new SelectList(naturezas, "ID_NTOP", "DESC_NTOP", this.nf.VENDAS.NATUREZAS_OPERACAO.ID_NTOP);
            }
            catch
            {
                this.ID_NTOP = new SelectList(naturezas, "ID_NTOP", "DESC_NTOP");
            }

            try
            {
                this.ID_NTOP_TRAN = new SelectList(naturezas, "ID_NTOP", "DESC_NTOP", this.nf.VENDAS.NATUREZAS_OPERACAO.ID_NTOP);
            }
            catch
            {
                this.ID_NTOP_TRAN = new SelectList(naturezas, "ID_NTOP", "DESC_NTOP");
            }

            this.ID_NTOP_ITVD = new SelectList(naturezas, "ID_NTOP", "DESC_NTOP");
            this.ID_UF = new SelectList(db.UFS, "CODIBGE_UF", "SIGLA_UF");
            this.ID_VEIC = new SelectList(db.VEICULOS, "ID_VEIC", "PLACA_VEIC");

            this.FINALIDADE_NF = new SelectList(FINALIDADE_NF, "Value", "Text", this.nf.FINALIDADE_NF);
            this.MODFRETE_NF = new SelectList(MODFRETE_NF, "Value", "Text", this.nf.VENDAS == null ? "" : this.nf.VENDAS.MODFRETE_VDA);
            this.AMBIENTE_NF = new SelectList(AMBIENTE_NF, "Value", "Text", this.nf.AMBIENTE_NF);
            this.TIPODANFE_NF = new SelectList(TIPODANFE_NF, "Value", "Text", this.nf.TIPODANFE_NF);
            this.TIPOEMISSAO_NF = new SelectList(TIPOEMISSAO_NF, "Value", "Text", this.nf.TIPOEMISSAO_NF);
            this.TIPOOP_NF = new SelectList(TIPOOP_NF, "Value", "Text", this.nf.TIPOOP_NF);

            this.CSOSN_ITVD = new SelectList(CSOSN_ITVD, "Value", "Text");
            this.SICMS_ITVD = new SelectList(SICMS_ITVD, "Value", "Text");
            this.SIPI_ITVD = new SelectList(SIPI_ITVD, "Value", "Text");
            this.INDTOT_ITVD = new SelectList(INDTOT_ITVD, "Value", "Text");
            this.MICMS_ITVD = new SelectList(MICMS_ITVD, "Value", "Text");
            this.MICMSST_ITVD = new SelectList(MICMSST_ITVD, "Value", "Text");
            this.MOTDESICMS_ITVD = new SelectList(MOTDESICMS_ITVD, "Value", "Text");
            this.OICMS_ITVD = new SelectList(OICMS_ITVD, "Value", "Text");
            this.SPISCOFINS_ITVD = new SelectList(SPISCOFINS_ITVD, "Value", "Text");
            this.SISSQN_ITVD = new SelectList(SISSQN_ITVD, "Value", "Text");
            this.TIPOCALCULO_ITVD = new SelectList(TIPOCALCULO_ITVD, "Value", "Text");
            this.TIPOESPECIFICO_ITVD = new SelectList(TIPOESPECIFICO_ITVD, "Value", "Text");

            this.CONDICAO_VEIC = new SelectList(CONDICAO_VEIC, "Value", "Text");
            this.CORDENATRAN_VEIC = new SelectList(CORDENATRAN_VEIC, "Value", "Text");
            this.ESPECIE_VEIC = new SelectList(ESPECIE_VEIC, "Value", "Text");
            this.RESTRICAO_VEIC = new SelectList(RESTRICAO_VEIC, "Value", "Text");
            this.TIPOCOMB_VEIC = new SelectList(TIPOCOMB_VEIC, "Value", "Text");
            this.TIPO_VEIC = new SelectList(TIPO_VEIC, "Value", "Text");
            this.TIPOOP_VEIC = new SelectList(TIPOOP_VEIC, "Value", "Text");
            this.VIN_VEIC = new SelectList(VIN_VEIC, "Value", "Text");

            this.TIPO_ARMA = new SelectList(TIPO_ARMA, "Value", "Text");
        }

        /// <summary>
        /// Retorna e atribui o status atual da nota fiscal
        /// </summary>
        /// <param name="STATUS_NF">A - Gravada
        ///                         B - Validada
        ///                         C - Assinada
        ///                         D - Autorizada
        ///                         E - Transmitida
        ///                         F - Rejeitada
        ///                         G - Cancelada
        ///                         H - Impressa</param>
        ///                         
        /// <returns></returns>
        public String SituacaoNF(String STATUS_NF)
        {
            NOTAS_FISCAIS n = db.NOTAS_FISCAIS.FirstOrDefault(t => t.ID_NF == this.nf.ID_NF);

            if (String.IsNullOrEmpty(STATUS_NF))
            {
                return String.Empty;
            }
            else
            {
                n.STATUS_NF = STATUS_NF;
                db.SaveChanges();

                switch (STATUS_NF)
                {
                    case "A":
                        return "Gravada";
                    case "B":
                        return "Validada";
                    case "C":
                        return "Assinada";
                    case "D":
                        return "Autorizada";
                    case "E":
                        return "Transmitida";
                    case "F":
                        return "Rejeitada";
                    case "G":
                        return "Cancelada";
                    case "H":
                        return "Impressa";
                    default:
                        return "Contingencia";
                }
            }
        }
    }
}